package cn.zn.framework.handler;

import cn.hutool.core.util.StrUtil;
import cn.zn.base.common.constant.Constants;
import cn.zn.base.common.utils.PasswordUtil;
import cn.zn.framework.bean.LoginUser;
import cn.zn.framework.utils.SecurityUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        //获取输入的用户名
        String username = authentication.getName();
        //获取输入的明文
        String rawPassword = (String) authentication.getCredentials();

        //查询用户是否存在
        LoginUser user = (LoginUser) userDetailsService.loadUserByUsername(username);

        if (StrUtil.endWith(username, Constants.SSO_TYPE)) {
            String loginName = StrUtil.subBefore(username, Constants.SSO_TYPE, true);
            if (!rawPassword.equals(SecurityUtil.getSsoPassword(loginName))) {
                throw new UsernameNotFoundException("单点登录Token验证失败");
            }
        } else {
            matchPassword(rawPassword, user.getPassword());
        }
        return new UsernamePasswordAuthenticationToken(user, rawPassword, user.getAuthorities());
    }

    /**
     * 密码验证
     *
     * @param rawPassword 明文
     * @param password    加密的密码
     */
    private void matchPassword(String rawPassword, String password) {
        if (!PasswordUtil.matchesPassword(rawPassword, password)) {
            throw new BadCredentialsException("Invalid Credentials");
        }
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }
}
